﻿/*  CLR版本: 4.0.30319.18063
 * 系统时间: 2014/10/31 14:20:43
 * 创建年份: 2014
 *     作者: 程炜.Snail
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace Quick.Communicator
{
    /// <summary>
    /// SocketAsyncEventArgs 对象池
    /// </summary>
    public class SocketAsyncEventArgsPool
    {
        MSQueue<SocketAsyncEventArgs> m_Pool;

        /// <summary>
        /// 初始化对象池SocketAsyncEventArgs
        /// </summary>
        public SocketAsyncEventArgsPool()
        {
            m_Pool = new MSQueue<SocketAsyncEventArgs>();
        }

        /// <summary>
        /// 往池中添加 SocketAsyncEventArg 对象
        /// </summary>
        /// <param name="item"></param>
        public void Push(SocketAsyncEventArgs item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null");
            }
            lock (m_Pool)
            {
                m_Pool.Enqueue(item);
            }
        }

        /// <summary>
        /// 移除 SocketAsyncEventArgs
        /// </summary>
        /// <returns></returns>
        public SocketAsyncEventArgs Pop()
        {
            lock (m_Pool)
            {
                return m_Pool.Dequeue();
            }
        }

        /// <summary>
        /// SocketAsyncEventArgs c池中数量
        /// </summary>
        public int Count
        {
            get { return m_Pool.Count; }
        }
        /// <summary>
        /// 自定义队列
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class MSQueue<T>
        {
            class Node
            {
                public T Value;
                public Pointer Next;
                public Node() { }
            }

            struct Pointer
            {
                public long Count;
                public Node Point;

                /// <summary>
                /// 
                /// </summary>
                /// <param name="p"></param>
                public Pointer(Pointer p)
                {
                    Point = p.Point;
                    Count = p.Count;
                }

                /// <summary>
                /// 
                /// </summary>
                /// <param name="node"></param>
                /// <param name="c"></param>
                public Pointer(Node node, long c)
                {
                    Point = node;
                    Count = c;
                }
            }
            private Pointer Head;
            private Pointer Tail;
            private int _Count;
            /// <summary>
            /// 队列中的可用数据
            /// </summary>
            public int Count
            {
                get { return _Count; }
            }
            public MSQueue()
            {
                _Count = 0;
                Node node = new Node();
                Head.Point = Tail.Point = node;
            }

            /// <summary>
            /// 比较并且替换
            /// </summary>
            /// <param name="destination"></param>
            /// <param name="compared"></param>
            /// <param name="exchange"></param>
            /// <returns></returns>
            private bool CAS(ref Pointer destination, Pointer compared, Pointer exchange)
            {
                if (compared.Point == Interlocked.CompareExchange(ref destination.Point, exchange.Point, compared.Point))
                {
                    Interlocked.Exchange(ref destination.Count, exchange.Count);
                    return true;
                }

                return false;
            }
            /// <summary>
            /// 移除并返回位于开始处的对象
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            public bool Dequeue(ref T t)
            {
                Pointer head;
                bool bDequeNotDone = true;
                while (bDequeNotDone)
                {
                    head = Head;
                    Pointer tail = Tail;
                    Pointer next = head.Point.Next;
                    if (head.Count == Head.Count && head.Point == Head.Point)
                    {
                        if (head.Point == tail.Point)
                        {
                            if (null == next.Point)
                            {
                                return false;
                            }
                            CAS(ref Tail, tail, new Pointer(next.Point, tail.Count + 1));

                        }
                        else
                        {
                            t = next.Point.Value;
                            _Count--;
                            if (CAS(ref Head, head, new Pointer(next.Point, head.Count + 1)))
                            {
                                bDequeNotDone = false;
                            }
                        }
                    }
                }
                return true;
            }
            /// <summary>
            /// 移除并返回位于开始处的对象
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            public T Dequeue()
            {
                T t = default(T);
                Pointer head;
                bool bDequeNotDone = true;
                while (bDequeNotDone)
                {
                    head = Head;
                    Pointer tail = Tail;
                    Pointer next = head.Point.Next;
                    if (head.Count == Head.Count && head.Point == Head.Point)
                    {
                        if (head.Point == tail.Point)
                        {
                            if (null == next.Point)
                            {
                                return t;
                            }
                            CAS(ref Tail, tail, new Pointer(next.Point, tail.Count + 1));
                        }
                        else
                        {
                            t = next.Point.Value;
                            _Count--;
                            if (CAS(ref Head, head, new Pointer(next.Point, head.Count + 1)))
                            {
                                bDequeNotDone = false;
                            }
                        }

                    }

                }
                return t;
            }
            /// <summary>
            /// 将对象添加到结尾处。
            /// </summary>
            /// <param name="t"></param>
            public void Enqueue(T t)
            {
                Node node = new Node();
                node.Value = t;
                _Count++;
                bool bEnqueueNotDone = true;

                while (bEnqueueNotDone)
                {
                    Pointer tail = Tail;
                    Pointer next = tail.Point.Next;
                    if (tail.Count == Tail.Count && tail.Point == Tail.Point)
                    {
                        if (null == next.Point)
                        {
                            if (CAS(ref tail.Point.Next, next, new Pointer(node, next.Count + 1)))
                            {
                                bEnqueueNotDone = false;
                            }
                        }
                        else
                        {
                            CAS(ref Tail, tail, new Pointer(next.Point, tail.Count + 1));
                        }
                    }
                }
            }
        }
    }
}
